home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9005.ZIP / SYCK.LST < prev    next >
File List  |  1990-03-23  |  17KB  |  689 lines

  1. _DLLs FOR DOS_
  2. by Gary Syck
  3.  
  4. [LISTING ONE]
  5.  
  6. // GETDATA.C    Read GBLDATA.OBJ to get global variables for DLLs
  7. //    02/12/89    by Gary Syck
  8. #include <stdio.h>
  9. #include <fcntl.h>
  10. #include <io.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <dos.h>
  14. #include "dll.h"
  15.  
  16. // Open GBLDATA and read data 
  17. void
  18. GetData()
  19. {
  20.     int fd;                // File descriptor for GBLDATA.OBJ
  21.     int    Idx;            // Index numbers from the file
  22.     unsigned long Elmnts, DSize;    // Number and size of global data items
  23.     unsigned PubGrp, PubSeg;    // Group and segment indexes for data
  24.     unsigned DOff;            // Offset for initialized data
  25.     unsigned char type;        // type of record read
  26.     int    size;            // size of the record
  27.     unsigned char *Data;        // the data to read
  28.     unsigned char *DSptr;        // Pointer to the Data segment
  29.     int i, j;
  30.  
  31.     if((fd=open( "gbldata.obj", O_BINARY|O_RDONLY )) == -1 )
  32.     {
  33.         printf( "Unable to open file\n" );
  34.         exit(1);
  35.     }
  36.     DataSize = 0;
  37.     SymCnt = 0;
  38.     AllocNumb = 0;
  39.     SymSize = 0;
  40.     type = 0;
  41.     DSptr = &DataSpace;
  42.     while( type != MODEND )
  43.     {
  44.         read( fd, (char *) &type, sizeof( unsigned char ));
  45.         read( fd, (char *) &size, sizeof( int ));
  46.         Data = malloc( size );
  47.         read( fd, Data, size );
  48.         switch( type )
  49.         {
  50.             case PUBDEF:    // The record contains public symbols
  51.                 i=0;
  52.                 if( Data[i]&0x80 )
  53.                 {
  54.                     PubGrp = (Data[i++]&0x7f)<<8;
  55.                     PubGrp += Data[i++];
  56.                 }
  57.                 else
  58.                     PubGrp = Data[i++];
  59.                 if( Data[i]&0x80 )
  60.                 {
  61.                     PubSeg = (Data[i++]&0x7f)<<8;
  62.                     PubSeg += Data[i++];
  63.                 }
  64.                 else
  65.                     PubSeg = Data[i++];
  66.                 if( PubSeg == 0 )
  67.                     i += 2;     // skip the frame number
  68.                 AllocateSyms();    // make memory for all symbols
  69.                 /* assume all public defs are in the DGROUP */
  70.                 while( i<size-1 )
  71.                 {
  72.                   Syms[SymCnt].Name = malloc( Data[i] + 2 );
  73.                   strncpy( Syms[SymCnt].Name, &Data[i+1], Data[i] );
  74.                   Syms[SymCnt].Name[Data[i]] = '\0';
  75.                   i += Data[i]+1;
  76.                   Syms[SymCnt].Seg = FP_SEG(DSptr);
  77.                   Syms[SymCnt].Offset = (FP_OFF(DSptr))+ *((int *) &Data[i] );
  78.                   SymCnt++;
  79.                   i += 2;
  80.                   if( Data[i]&0x80 ) // skip over the type
  81.                   {
  82.                         Idx = (Data[i++]&0x7f)<<8;
  83.                         Idx += Data[i++];
  84.                   }
  85.                     else
  86.                         Idx = Data[i++];
  87.                 }
  88.                 break;
  89.             case LEDATA: // record contains data for data segment
  90.                 i = 0;
  91.                 if( Data[i]&0x80 )
  92.                 {
  93.                     Idx = (Data[i++]&0x7f)<<8;
  94.                     Idx += Data[i++];
  95.                 }
  96.                 else
  97.                     Idx = Data[i++];
  98.                 /* Assume all data is for the data segment */
  99.                 DOff = *((int *) &Data[i] );
  100.                 i += 2;
  101.                 memcpy( &DSptr[DOff], &Data[i], size-(i+1) );
  102.                 if( DataSize < DOff + size - (i+1))
  103.                     DataSize = DOff + size - (i+1);
  104.                 break;
  105.             case COMDEF:  // record contains uninitialized data
  106.                 i = 0;
  107.                 while( i < size-1 )
  108.                 {
  109.                  Syms[SymCnt].Name = malloc( Data[i]+2 );
  110.                  strncpy( Syms[SymCnt].Name, &Data[i+1], Data[i] );
  111.                  Syms[SymCnt].Name[Data[i]] = '\0';
  112.                  i += Data[i] + 2;
  113.                  if( Data[i++] == 0x61 )
  114.                 {
  115.                     if( Data[i] < 128 )
  116.                       Elmnts = (unsigned long) Data[i++];
  117.                       else
  118.                       {
  119.                       j = Data[i++] - 127;
  120.                       Elmnts = 0L;
  121.                       memcpy( &Elmnts, &Data[i], j );
  122.                       i += j;
  123.                       }
  124.                      if( Data[i] < 128 )
  125.                      DSize = (unsigned long) Data[i++];
  126.                      else
  127.                      {
  128.                      j = Data[i++] - 127;
  129.                      DSize = 0L;
  130.                      memcpy( &DSize, &Data[i], j );
  131.                      i += j;
  132.                      }
  133.                      Syms[SymCnt].Size = (unsigned) (Elmnts * DSize);
  134.                      if( (unsigned long) SymSize + (unsigned long) (Elmnts * DSize) >= 32000L )
  135.                      AllocateSyms();
  136.                      SymSize += (unsigned) (Elmnts * DSize);
  137.                      SymCnt++;
  138.                     }
  139.                 }
  140.                 break;
  141.             default:
  142.                 break;
  143.         }
  144.         free( Data );
  145.     }
  146.     close( fd );
  147.     AllocateSyms();    // make memory for all of the symbols
  148. }
  149.  
  150. // make a memory block to hold the previous symbols
  151. void
  152. AllocateSyms()
  153. {
  154.     char *Buff;
  155.     unsigned Seg, Off;
  156.     if( SymSize )
  157.     {
  158.         Buff = malloc( SymSize );
  159.         Seg = FP_SEG( Buff );
  160.         Off = FP_OFF( Buff );
  161.         SymSize = 0;
  162.         while( AllocNumb < SymCnt )
  163.         {
  164.             Syms[AllocNumb].Seg = Seg;
  165.             Syms[AllocNumb].Offset = Off;
  166.             Off += Syms[AllocNumb].Size;
  167.             AllocNumb++;
  168.         }
  169.     }
  170. }
  171.  
  172.  
  173. [LISTING TWO]
  174.  
  175. ; STUB.ASM  Used by DLL to see if a function needs to be loaded.
  176. ; 02/12/89  By Gary Syck
  177.  
  178.     TITLE   stub.asm
  179.     NAME    stub
  180.  
  181.     .8087
  182. STUB_TEXT    SEGMENT  WORD PUBLIC 'CODE'
  183. STUB_TEXT    ENDS
  184. _DATA    SEGMENT  WORD PUBLIC 'DATA'
  185. _DATA    ENDS
  186. CONST    SEGMENT  WORD PUBLIC 'CONST'
  187. CONST    ENDS
  188. _BSS    SEGMENT  WORD PUBLIC 'BSS'
  189. _BSS    ENDS
  190. DGROUP    GROUP    CONST, _BSS, _DATA
  191.     ASSUME  CS: STUB_TEXT, DS: DGROUP, SS: DGROUP
  192. EXTRN    _LoadFunc:FAR        ; Function to get a function into memory
  193. EXTRN    _FuncLst:DWORD        ; The function table
  194. _DATA    SEGMENT
  195.     PUBLIC    _DataSpace
  196. _DataSpace    db 32000 dup(?)
  197. _DATA    ENDS
  198. STUB_TEXT      SEGMENT
  199.     ASSUME    CS: STUB_TEXT
  200.     PUBLIC    _Stub
  201. _Stub    PROC FAR
  202.     mov    bx,offset _FuncLst    ; this is modified before use
  203.     mov    ax,seg _FuncLst
  204.     mov    es,ax
  205.     mov    ax,WORD PTR es:[bx+4]    ; check .Loc
  206.     or    ax,WORD PTR es:[bx+6]
  207.     jne    noload
  208.     push    es            ; save ES and BX
  209.     push    bx
  210.     call    FAR PTR _LoadFunc
  211.     pop    bx
  212.     pop    es
  213. noload:
  214.     jmp    DWORD PTR es:[bx+4]    ; go to the function
  215. _Stub    ENDP
  216. STUB_TEXT    ENDS
  217. END
  218.  
  219.  
  220. [LISTING THREE]
  221.  
  222. // LINKER.C Link a module at run time
  223. // 02/12/89 by Gary Syck
  224. #include <stdio.h>
  225. #include <string.h>
  226. #include <fcntl.h>
  227. #include <io.h>
  228. #include <stdlib.h>
  229. #include "dll.h"
  230.  
  231. // Load the function in the FUNCTAB entry
  232. void
  233. LoadFunc( FUNCTAB *func )
  234. {
  235.     char FileName[15], *p, Name[80];
  236.     int    fd;
  237.     unsigned char type;
  238.     int size;
  239.     unsigned char *Data, *Dp, *LastFunc;
  240.     int i, j, ln;
  241.     unsigned pubgrp, pubseg, dataseg;
  242.     unsigned DROff, Loc, FixDat;
  243.     unsigned FrameIdx, TargetIdx, TargetDisp, tmp;
  244.     unsigned long ltmp;
  245.     int dataoff;
  246.     unsigned LocalSize;    // size of the data allocated here
  247.     struct {
  248.         int    Flag;        // 1 = data, 2 = function
  249.         int SymNumb;    // What symbol
  250.     } ExtSyms[20];
  251.     int ExtCnt;
  252.     struct {
  253.         int FuncNumb;
  254.         int OffSet;
  255.     } Pubs[10];
  256.     int PubCnt;
  257.     struct {
  258.         unsigned Meth;    // The method to use
  259.         unsigned Idx;    // The index
  260.     } Threads[8];
  261.     void *ptr;
  262.     unsigned char *DSptr;
  263.     unsigned constseg;    // Where constants begin
  264.  
  265.     strncpy( FileName, &func->Name[1], 14 );
  266.     FileName[14] = '\0';
  267.     if((p=strchr( FileName, '#' )) != NULL )
  268.         *p = '\0';
  269.     strcat( FileName, ".obj" );
  270.     if((fd=open( FileName, O_RDONLY|O_BINARY )) == -1 )
  271.     {
  272.         printf( "Unable to open file: %s\n", FileName );
  273.         return;
  274.     }
  275.     LocalSize = 0;
  276.     ExtCnt = 0;
  277.     PubCnt = 0;
  278.     type = 0;
  279.     DSptr = &DataSpace;
  280.     while( type != MODEND )
  281.     {
  282.         read( fd, (char *) &type, sizeof( unsigned char ));
  283.         read( fd, (char *) &size, sizeof( int ));
  284.         Data = malloc( size );
  285.         read( fd, Data, size );
  286.         switch( type )
  287.         {
  288.             case THEADR:    // ignore the header
  289.             case COMMENT:    // ignore comments
  290.             case GRPDEF:    // these are always the same
  291.             case MODEND:
  292.             case SEGDEF:
  293.             case LNAMES:
  294.                 break;
  295.             case EXTDEF:    // find external names
  296.                 for( i=0; i<size-1; i += ln+2 )
  297.                 {
  298.                   ln = Data[i];
  299.                   if( ln )
  300.                   {
  301.                     strncpy( Name, &Data[i+1], ln );
  302.                     Name[ln] = '\0';
  303.                     for( j=0; j<SymCnt && strcmp(Syms[j].Name, Name );j++);
  304.                     if( j<SymCnt )
  305.                     {
  306.                     ExtSyms[ExtCnt].Flag = 1;
  307.                     ExtSyms[ExtCnt].SymNumb = j;
  308.                     }
  309.                     else
  310.                     {
  311.                     for( j=0; j<FuncCnt
  312.                     && strcmp( FuncLst[j].Name,Name );j++);
  313.                     if( j>=FuncCnt ) // make space for it
  314.                         {
  315.                         FuncLst[FuncCnt].Name = 
  316.                                                        malloc(strlen(Name)+2 );
  317.                      strcpy( FuncLst[FuncCnt].Name, Name );
  318.                     FuncLst[FuncCnt].Loc = NULL;
  319.                     FuncLst[FuncCnt].Flag = 0;
  320.                     memcpy( FuncLst[FuncCnt].Stub, Stub, STUBSIZE );
  321.                     memcpy(&FuncLst[FuncCnt].Stub[4],&FuncLst[FuncCnt],2);FuncCnt++;
  322.                         }
  323.                         ExtSyms[ExtCnt].Flag = 2;
  324.                         ExtSyms[ExtCnt].SymNumb = j;
  325.                     }
  326.                     ExtCnt++;
  327.                     }
  328.                 }
  329.                 break;
  330.             case PUBDEF:    // add to list of available functions
  331.                 i = 0;
  332.                 if( Data[i]&0x80 )
  333.                 {
  334.                     pubgrp = (Data[i++]&0x7f) << 8;
  335.                     pubgrp += Data[i++];
  336.                 }
  337.                 else
  338.                     pubgrp = Data[i++];
  339.                 if( Data[i]&0x80 )
  340.                 {
  341.                     pubseg = (Data[i++]&0x7f) << 8;
  342.                     pubseg += Data[i++];
  343.                 }
  344.                 else
  345.                     pubseg = Data[i++];
  346.                 if( pubseg == 0 )    // skip the frame
  347.                     i += 2;
  348.                 while( i < size-1 )
  349.                 {
  350.                     ln = Data[i];
  351.                     if( ln )
  352.                     {
  353.                          strncpy( Name, &Data[i+1], ln );
  354.                          Name[ln] = '\0';
  355.                     }
  356.                     i += ln + 1;
  357.                     memcpy( &ln, &Data[i], sizeof( int ));
  358.                     i += 2;
  359.                     if( Data[i]&0x80 )
  360.                         i += 2;
  361.                     else
  362.                         i++;
  363.                     for( j=0; j<FuncCnt
  364.                          && strcmp( FuncLst[j].Name, Name ); j++ );
  365.                     Pubs[PubCnt].FuncNumb = j;
  366.                     Pubs[PubCnt].OffSet = ln;
  367.                     PubCnt++;
  368.                 }
  369.                 break;
  370.             case LEDATA:
  371.                 i = 0;
  372.                 if( Data[i]&0x80 )
  373.                 {
  374.                     dataseg = (Data[i++]&0x7f) << 8;
  375.                     dataseg += Data[i++];
  376.                 }
  377.                 else
  378.                     dataseg = Data[i++];
  379.                 memcpy( &dataoff, &Data[i], sizeof( int ));
  380.                 i += sizeof( int );
  381.                 if( dataseg == 2 ) // it's for the data segment
  382.                 {
  383.                     Dp = &DSptr[DataSize+dataoff];
  384.                     memcpy( Dp, &Data[i], size - ( i+1 ));
  385.                     if( LocalSize < dataoff + size - (i+1))
  386.                         LocalSize = dataoff + size - (i+1);
  387.                     constseg = LocalSize+DataSize;
  388.                 }
  389.                 else if( dataseg == 3 ) // for const segment
  390.                 {
  391.                     Dp = &DSptr[constseg+dataoff];
  392.                     memcpy( Dp, &Data[i], size - ( i+1 ));
  393.                     if( LocalSize < dataoff + size - (i+1))
  394.                         LocalSize = dataoff + size - (i+1);
  395.                 }
  396.                 else    // here is the code
  397.                 {
  398.                     if( dataoff == 0 ) LastFunc = malloc( size - (i+1) );
  399.                     else
  400.                       LastFunc = realloc( LastFunc, size - (i+1) + dataoff );
  401.                     Dp = &LastFunc[dataoff];
  402.                     memcpy( Dp, &Data[i], size-(i+1));
  403.                     for( j=0; j<PubCnt; j++ ) 
  404.                     {
  405.                         FuncLst[Pubs[j].FuncNumb].Loc = &LastFunc[Pubs[j].OffSet];
  406.                     }
  407.                 }
  408.                 break;
  409.             case FIXUPP: // only look at the fixup fields all 
  410.                                      // threads are the same.
  411.                 i = 0;
  412.                 while( i < size-1 )
  413.                 {
  414.                     if( (Data[i])&0x80 )    // its a fixup
  415.                     {
  416.                      DROff = ((Data[i]&3)<<8) + Data[i+1];
  417.                      Loc = Data[i];
  418.                      i += 2;
  419.                      FixDat = Data[i++];
  420.                      FrameIdx = TargetIdx = TargetDisp = 0;
  421.                      if( !(FixDat&0x80) && (FixDat&0x70) != 0x50 )
  422.                         /* there is a frame index */
  423.                      {
  424.                         if( Data[i]&0x80 )
  425.                         {
  426.                           FrameIdx = (Data[i++]&0x7f) << 8;
  427.                           FrameIdx += Data[i++];
  428.                     }
  429.                         else
  430.                             FrameIdx = Data[i++];
  431.                     }
  432.                     if( !(FixDat&8) ) /* thread index */
  433.                     {
  434.                     if( Data[i]&0x80 )
  435.                     {
  436.                     TargetIdx = (Data[i++]&0x7f) << 8;
  437.                                TargetIdx += Data[i++];
  438.                     }
  439.                     else
  440.                     TargetIdx = Data[i++];
  441.                     }
  442.                     if( !(FixDat&4) ) 
  443.                     {
  444.                     memcpy( &TargetDisp, &Data[i], sizeof( int ));
  445.                         i += 2;
  446.                     }
  447.                     /* fix up FixDat from threads */
  448.                     if( FixDat&0x80 ) // frame from thread
  449.                     {
  450.                         j = ((FixDat&0x70)>>4) + 4;
  451.                         tmp = Threads[j].Meth << 4;
  452.                         FixDat = (FixDat&0xf) | tmp;
  453.                            FrameIdx = Threads[j].Idx;
  454.                     }
  455.                     if( FixDat&8 ) // target from a thread
  456.                     {
  457.                        j = FixDat&3;
  458.                        tmp = Threads[j].Meth&3;
  459.                        FixDat = (FixDat&0xf4) | tmp;
  460.                        TargetIdx = Threads[j].Idx;
  461.                     }
  462.                     switch( Loc&0x1C ) // find what we need
  463.                     {
  464.                     case 0x4:    // offset fixup
  465.                        if( (FixDat&7) == 4 ) 
  466.                         {
  467.                        /* get the value to be fixed */
  468.                         memcpy( &tmp, &Dp[DROff], sizeof(int));
  469.                           if( TargetIdx == 2 ) // data seg
  470.                                {
  471.                            tmp += ((unsigned long)
  472.                               &DSptr[DataSize])&0xffff;
  473.                             }
  474.                         else if( TargetIdx == 3 )
  475.                                                        {
  476.                            tmp += ((unsigned long)
  477.                              &DSptr[constseg])&0xffff;
  478.                             }
  479.                           /* put the fixed number back */
  480.                           memcpy( &Dp[DROff], &tmp, 
  481.                                                                   sizeof(int));
  482.                             }
  483.                         else if((FixDat&7) == 6 ) 
  484.                             {
  485.                         if( !(Loc&0x40) ) 
  486.                           {
  487.                           ltmp = (unsigned long)
  488.                           (FuncLst[ExtSyms[TargetIdx-1]
  489.                            .SymNumb].Loc);
  490.                            ltmp -= (unsigned long) (&Dp[DROff])+2L;
  491.                             memcpy( &Dp[DROff],<mp, sizeof(int));
  492.                             }
  493.                              else // put the offset in
  494.                             {
  495.                             memcpy( &Dp[DROff],&Syms[ExtSyms[TargetIdx-1].SymNumb].Offset, sizeof( int ));
  496.                              }
  497.                         }
  498.                         break;
  499.                         case 0x8:  // segment fixup
  500.                         if( (FixDat&7) == 6 ) 
  501.                         {
  502.                         memcpy( &Dp[DROff], &Syms[ExtSyms[TargetIdx-1].SymNumb].Seg, sizeof( int ));
  503.                         }
  504.                         break;
  505.                         case 0xC: // symbol from target
  506.                         if( (FixDat&7) == 6 ) 
  507.                         {
  508.                         ptr = FuncLst[ExtSyms
  509.                                                    [TargetIdx-1].SymNumb].Stub;
  510.                            memcpy( &Dp[DROff], &ptr, 
  511.                                                               sizeof( void *));
  512.                          }
  513.                         break;
  514.                         }
  515.                     }
  516.                     else    // its a thread
  517.                     {
  518.                         j = Data[i]&3;
  519.                         if( Data[i]&0x40 )
  520.                             j += 4;
  521.                            Threads[j].Meth = (Data[i]&0x1C)>>2;
  522.                        i++;
  523.                        if( Data[i]&0x80 )
  524.                        {
  525.                         tmp = (Data[i++]&0x7f) << 8;
  526.                         tmp += Data[i++];
  527.                        }
  528.                         else
  529.                         tmp = Data[i++];
  530.                         Threads[j].Idx = tmp;
  531.                     }
  532.                 }
  533.                 break;
  534.             default:
  535.              printf( "invalid record: %x size: %d\n", type, size );
  536.              break;
  537.         }
  538.         free( Data );
  539.     }
  540.     close( fd );
  541.     DataSize += LocalSize;
  542. }
  543.  
  544. [LISTING FOUR]
  545.  
  546. // DLL.C Implement DLLs for DOS
  547. // 02/12/89 by Gary Syck
  548. #include <stdio.h>
  549. #include <stdlib.h>
  550. #include <string.h>
  551. #define MAIN
  552. #include "dll.h"
  553.  
  554. void
  555. main( int argc, char *argv[] )
  556. {
  557.     void (*func)(void);
  558.     unsigned char *ptr;
  559.  
  560.     GetData();                // Read the global data
  561.     FuncCnt = 2;                // make two functions
  562.     FuncLst[0].Name = malloc( 10 );
  563.     strcpy( FuncLst[0].Name, "_printf" );    // The library function printf
  564.     FuncLst[0].Loc = printf;
  565.     FuncLst[0].Flag = 1;
  566.     memcpy( FuncLst[0].Stub, &Stub, STUBSIZE );
  567.     ptr = FuncLst;
  568.     memcpy( &FuncLst[0].Stub[1], &ptr, 2 );
  569.  
  570.     FuncLst[1].Name = malloc( 10 );
  571.     strcpy( FuncLst[1].Name, "_main" );       // The first function to run
  572.     FuncLst[1].Loc = NULL;
  573.     FuncLst[1].Flag = 0;
  574.     memcpy( FuncLst[1].Stub, &Stub, STUBSIZE );
  575.     ptr = &FuncLst[1];
  576.     memcpy( &FuncLst[1].Stub[1], &ptr, 2 );
  577.     func = FuncLst[1].Stub;
  578.     (*func)();    // Call the main function
  579. }
  580.  
  581.  
  582.  
  583. [LISTING FIVE]
  584.  
  585. // Global data to be used with sample DLL
  586.  
  587. // make various data items
  588.  
  589. char Str[] = "Tester equals";
  590. int Flubber=20;
  591. int Tester=14;
  592.  
  593.  
  594.  
  595.  
  596. [LISTING SIX]
  597.  
  598. // sample DLL routine
  599. #include <stdio.h>
  600.  
  601. void main(void);
  602. void Test(void);
  603.  
  604. extern int Flubber;
  605. extern char Str[];
  606. extern int Tester;
  607.  
  608. // print hello world and the value of Flubber then call Test
  609. void
  610. main()
  611. {
  612.     printf( "Hello, world: %d\n", Flubber );
  613.     Test();
  614. }
  615.  
  616. // print a message and the values of Str and Tester
  617. void
  618. Test()
  619. {
  620.     printf( "This is a test function\n%s: %d\n", Str, Tester );
  621. }
  622.  
  623.  
  624.  
  625. [LISTING SEVEN]
  626.  
  627. // DLL.H  Include file for DLL
  628. // 02/12/89 By Gary Syck
  629.  
  630. #ifdef MAIN
  631. #define EXTERN
  632. #else
  633. #define EXTERN extern
  634. #endif
  635.  
  636. typedef struct {
  637.     char         *Name;        // Name of the symbol
  638.     unsigned    Size;        // size of the symbol
  639.     unsigned    Seg;        // Segment containing the symbol
  640.     unsigned    Offset;        // Offset for the symbol
  641. } SYMTAB;
  642.  
  643. #define STUBSIZE 50
  644. typedef struct {
  645.     char        *Name;        // name of the function
  646.     void        *Loc;        // where the function is stored
  647.     int            Flag;    // true if function is executing
  648.     unsigned char Stub[STUBSIZE];    // Function to call this function
  649. } FUNCTAB;
  650.  
  651. SYMTAB Syms[200];            // the symbols found
  652. EXTERN int    SymCnt;            // The number of symbols
  653. EXTERN int    AllocNumb;        // The first symbol in the current
  654.                     // allocation block
  655. EXTERN SYMTAB    Syms[];            // list of symbols
  656. EXTERN int SymCnt;            // number of symbols
  657. EXTERN unsigned SymSize;        // running total of the size of stuff
  658. EXTERN int    DataSize;        // how many bytes in DataSpace are used
  659.  
  660. EXTERN FUNCTAB FuncLst[100];        // the list of functions
  661. EXTERN int     FuncCnt;        // The number of allocated entries
  662.  
  663. extern    unsigned char DataSpace;    // room in the data segment
  664. extern char Stub;            // This is really a function. It is 
  665.                                         // used this way to make sure the 
  666.                                         // segment gets used in memcpy
  667. /* record types */
  668. #define THEADR        0x80
  669. #define COMMENT    0x88
  670. #define MODEND        0x8A
  671. #define EXTDEF        0x8C
  672. #define TYPDEF        0x8E
  673. #define PUBDEF        0x90
  674. #define LINNUM        0x94
  675. #define LNAMES        0x96
  676. #define SEGDEF        0x98
  677. #define GRPDEF        0x9A
  678. #define FIXUPP        0x9C
  679. #define LEDATA        0xA0
  680. #define LIDATA        0xA2
  681. #define COMDEF        0xB0
  682.  
  683. // Function prototypes
  684. void main( int argc, char *argv[] );
  685. void LoadFunc( FUNCTAB *Func );
  686. void GetData(void);
  687. void AllocateSyms(void);
  688.  
  689.